﻿using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections.Specialized;
using System.Web.UI;
using MyHealthByDesign.Domain.Processing;

namespace MyHealthByDesign.Domain.Panels
{
    /// <summary>
    /// Description:
    /// CheckBoxList class provides functionality for CheckBoxList Questions.
    /// 
    /// Author: Mark Servais
    /// Date Created: 10/23/2011
    /// 
    /// Other code files referenced:
    /// IQuestionPanel.cs
    /// 
    /// Regression Test Information:
    /// CheckBoxList_Test.cs in project MyHealthByDesign_Test
    /// 
    /// Revision History:
    /// 10/25/2011 Mark Servais - Added function to retreive question value for type.
    /// 10/27/2011 Mark Servais - Fixed bugs for options and specials.
    /// 10/28/2011 Mark Servais - Fixed Client ID logic.
    /// 11/03/2011 Mark Servais - Added methods to set initial question values from database and 
    ///                             added new CSS options for labels and options
    /// 11/06/2011 Mark Servais - Fixed model help pop-ups by inserting proper style class
    /// 11/18/2011 Mark Servais - Added Help URL link for options
    /// 11/22/2011 Mark Servais - Added ability to process attributes for HTML rendering
    /// 12/04/2011 Mark Servais - Add administration form creation and processing
    /// 12/11/2011 Mark Servais - Add option maintenance
    /// 
    /// Known Faults:
    /// None.
    /// </summary>
    public class CheckBoxList : IQuestionPanel
    {
        #region IQuestionPanel Members

        /// <summary>
        /// GenerateQuestionDisplay - Generates Panel for question to display on
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel control is returned based on question passed
        /// </summary>
        /// <param name="question"></param>
        /// <returns></returns>
        public System.Web.UI.WebControls.Panel GenerateQuestionDisplay(Question question)
        {
            Panel pnlIn = new Panel();

            Panel pnlTopic = new Panel();
            
            Label lblC = new Label();
            lblC.Text = question.ContentLabel;
            lblC.CssClass = "panelLeftListHeader";

            pnlTopic.Controls.Add(lblC);

            if (!string.IsNullOrEmpty(question.FieldHelpText) && !string.IsNullOrEmpty(question.FieldHelpURL))
            {
                HtmlGenericControl aHelp = new HtmlGenericControl("a");
                aHelp.Attributes.Add("href", question.FieldHelpURL);
                aHelp.Attributes.Add("class", "helplink");
                aHelp.InnerText = question.FieldHelpText;
                pnlTopic.Controls.Add(aHelp);
            }

            pnlIn.Controls.Add(pnlTopic);

            List<QuestionOption> FieldOptions = new List<QuestionOption>();
            
            // load Generic Lists
            FieldOptions = question.FieldOptions;
            
            foreach (QuestionOption questionOption in FieldOptions)
            {
                Panel pnlOPtion = new Panel();

                Type typField = typeof(CheckBox).Assembly.GetType("System.Web.UI.WebControls.CheckBox");
                CheckBox cb = (CheckBox)Activator.CreateInstance(typField);

                cb.ID = questionOption.Name;
                cb.ClientIDMode = ClientIDMode.Static;
                cb.CssClass = questionOption.OptionCSS;
                pnlOPtion.Controls.Add(cb);

                // check for special processing
                foreach (QuestionProcessing questionProcessing in question.Processing)
                {
                    if (questionProcessing.FieldName == questionOption.Name)
                    {
                        Type typProcess =
                            typeof(IProcessing).Assembly.GetType(questionProcessing.QuestionProcessingType);
                        IProcessing process = (IProcessing)Activator.CreateInstance(typProcess);

                        process.RunProcessingForField(question, questionProcessing);
                    }
                }

                //apply attributes
                foreach (HtmlAttribute attribute in question.Attributes)
                {
                    if (attribute.ForFieldName == questionOption.Name)
                    {
                        cb.Attributes.Add(attribute.Keyword, attribute.Statement);
                    }
                }

                if (!string.IsNullOrEmpty(questionOption.OptionHelpURL))
                {
                    HtmlGenericControl aHelp = new HtmlGenericControl("a");
                    aHelp.Attributes.Add("href", questionOption.OptionHelpURL);
                    aHelp.Attributes.Add("class", "helplink");
                    aHelp.InnerText = "&nbsp;&nbsp;" + questionOption.OptionLabel + "&nbsp;&nbsp;";
                    pnlOPtion.Controls.Add(aHelp);
                }
                else
                {
                    Label lblSuffix = new Label();
                    lblSuffix.Text = "&nbsp;&nbsp;" + questionOption.OptionLabel + "&nbsp;&nbsp;";
                    pnlOPtion.Controls.Add(lblSuffix);
                }
                

                if (questionOption.Specials != null)
                {
                    //create control
                    foreach (OptionSpecial optionSpecial in questionOption.Specials)
                    {
                        switch (optionSpecial.DisplayType)
                        {
                            case "System.Web.UI.WebControls.TextBox":
                                Type typFieldOpt = typeof (TextBox).Assembly.GetType("System.Web.UI.WebControls.TextBox");
                                TextBox tbOpt = (TextBox) Activator.CreateInstance(typFieldOpt);

                                tbOpt.ID = optionSpecial.Name;
                                tbOpt.CssClass = question.FieldCSS;
                                pnlOPtion.Controls.Add(tbOpt);
                                break;
                        }
                    }
                }

                pnlIn.Controls.Add(pnlOPtion);

            }

            return pnlIn;
        }

        /// <summary>
        /// RetrieveQuestionValue - Retrieves the question values based on
        /// display type
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Dictionary object is returned with question and fieldname, answer collection
        /// </summary>
        /// <param name="question"></param>
        /// <param name="contentPlaceHolder"></param>
        /// <returns></returns>
        public Dictionary<Question, NameValueCollection> RetrieveQuestionValue(Question question, ContentPlaceHolder contentPlaceHolder)
        {
            Dictionary<Question, NameValueCollection> dFieldValues = new Dictionary<Question, NameValueCollection>();
            NameValueCollection nvc = new NameValueCollection();

            List<QuestionOption> fieldOptions = question.FieldOptions;

            if (fieldOptions != null && fieldOptions.Count > 0)
            {
                foreach (QuestionOption questionOption in fieldOptions)
                {
                    CheckBox cb = (CheckBox)contentPlaceHolder.FindControl(questionOption.Name);
                    nvc.Add(questionOption.Name, cb.Checked.ToString());
                    if ((questionOption.Specials != null) && (cb.Checked))
                    {
                        foreach (OptionSpecial optionSpecial in questionOption.Specials)
                        {
                            TextBox tb = (TextBox)contentPlaceHolder.FindControl(optionSpecial.Name);
                            nvc.Add(optionSpecial.Name, tb.Text);
                        }
                    }
                }

                dFieldValues.Add(question, nvc); 
            }

            return dFieldValues;
        }

        /// <summary>
        /// SetInitialQuestionValue - Set the question values based on
        /// display type, field name, and databse value
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Field to be placed in panel will be set with database value
        /// </summary>
        /// <param name="question"></param>
        /// <param name="answers"></param>
        /// <param name="contentPlaceHolder"></param>
        public void SetInitialQuestionValue(Question question, NameValueCollection answers, ContentPlaceHolder contentPlaceHolder)
        {
            List<QuestionOption> fieldOptions = question.FieldOptions;

            foreach (QuestionOption qOpt in fieldOptions)
            {
                CheckBox cb = (CheckBox)contentPlaceHolder.FindControl(qOpt.Name);
                cb.Checked = Convert.ToBoolean(answers.Get(qOpt.Name));
                
                if ((qOpt.Specials != null) && (cb.Checked))
                {
                    foreach (OptionSpecial os in qOpt.Specials)
                    {
                        TextBox tb = (TextBox)contentPlaceHolder.FindControl(os.Name);
                        tb.Text = answers.Get(os.Name);
                    }
                }
            }
        }

        /// <summary>
        /// GenerateAdminForm - Generates Panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel control is returned based on question passed
        /// </summary>
        /// <param name="question"></param>
        /// <param name="panelList"></param>
        /// <returns></returns>
        public List<Panel> GenerateAdminForm(Question question, List<Panel> panelList)
        {
            List<Panel> listPanels = new List<Panel>();
            Panel panelBuild;

            foreach (Panel panel in panelList)
            {
                panelBuild = panel;
                switch (panel.ID)
                {
                    case "pnlQuestionCore":
                        BuildQuestionPanel(ref panelBuild, question);
                        break;
                    case "pnlOptions":
                        BuildOptionPanel(ref panelBuild, question);
                        break;
                    case "pnlProcessingRules":
                        BuildProcessingPanel(ref panelBuild);
                        break;
                }
                listPanels.Add(panelBuild);

            }

            return listPanels;
        }

        /// <summary>
        /// BuildProcessingPanel - Generates core question panel
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel is updated for collection reference
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private void BuildProcessingPanel(ref Panel panel)
        {
            panel.Visible = false;
            //TODO Add processing logic
        }

        /// <summary>
        /// BuildOptionPanel - Generates core question panel
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel is updated for collection reference
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private void BuildOptionPanel(ref Panel panel, Question question)
        {
            if (question.FieldOptions != null)
            {
                Domain domain = new Domain();

                // commonly used controls
                HtmlGenericControl listItem;
                HtmlGenericControl fieldLabel;

                // create inner panel
                Panel pnlOptions = new Panel();

                // insert header
                Panel pnlOptionItem = new Panel();
                pnlOptionItem.Attributes.Add("class", "optionsHeader");
                fieldLabel = new HtmlGenericControl("label");
                fieldLabel.InnerText = "Current Options:";

                pnlOptionItem.Controls.Add(fieldLabel);

                pnlOptions.Controls.Add(pnlOptionItem);


                foreach (QuestionOption qo in question.FieldOptions)
                {
                    // create value item
                    pnlOptionItem = new Panel();
                    pnlOptionItem.Attributes.Add("class", "options");
                    fieldLabel = new HtmlGenericControl("label");
                    fieldLabel.InnerText = qo.OptionLabel;

                    pnlOptionItem.Controls.Add(fieldLabel);

                    pnlOptions.Controls.Add(pnlOptionItem);

                }

                panel.Controls.Add(pnlOptions);

                panel.Visible = true;
            }
            else
            {
                panel.Visible = false;
            }
        }

        /// <summary>
        /// BuildQuestionPanel - Generates core question panel
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel is updated for collection reference
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private void BuildQuestionPanel(ref Panel panel, Question question)
        {
            Domain domain = new Domain();
            bool bUpdate = false;

            if (question.Id != 0)
                bUpdate = true;


            // commonly used controls
            HtmlGenericControl listItem;
            HtmlGenericControl fieldLabel;

            panel.Visible = true;

            // create unordered list
            HtmlGenericControl uList = new HtmlGenericControl("ul");

            // create field type dropdown
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionType");
            fieldLabel.InnerText = "Question Type";

            listItem.Controls.Add(fieldLabel);

            DropDownList ddlQuestionTypes = new DropDownList();
            ddlQuestionTypes.ID = "ddlQuestionTypes";
            ddlQuestionTypes.ClientIDMode = ClientIDMode.Static;

            ddlQuestionTypes.Items.Add(new ListItem("SimpleTextBox", "MyHealthByDesign.Domain.Panels.SimpleTextBox"));
            ddlQuestionTypes.Items.Add(new ListItem("TextBoxWithChecklist", "MyHealthByDesign.Domain.Panels.TextBoxWithChecklist"));
            ddlQuestionTypes.Items.Add(new ListItem("SimpleDropDownList", "MyHealthByDesign.Domain.Panels.SimpleDropDownList"));
            ddlQuestionTypes.Items.Add(new ListItem("SimpleCheckBox", "MyHealthByDesign.Domain.Panels.SimpleCheckBox"));
            ddlQuestionTypes.Items.Add(new ListItem("RangeDropDownList", "MyHealthByDesign.Domain.Panels.RangeDropDownList"));
            ddlQuestionTypes.Items.Add(new ListItem("RadioList", "MyHealthByDesign.Domain.Panels.RadioList"));
            ddlQuestionTypes.Items.Add(new ListItem("MultipleTextBoxes", "MyHealthByDesign.Domain.Panels.MultipleTextBoxes"));
            ddlQuestionTypes.Items.Add(new ListItem("LongLabelMessageBox", "MyHealthByDesign.Domain.Panels.LongLabelMessageBox"));
            ddlQuestionTypes.Items.Add(new ListItem("CheckBoxList", "MyHealthByDesign.Domain.Panels.CheckBoxList"));

            foreach (ListItem item in ddlQuestionTypes.Items)
            {
                if (question.DisplayType == item.Value)
                    item.Selected = true;
                else
                    item.Enabled = false;
            }

            listItem.Controls.Add(ddlQuestionTypes);

            uList.Controls.Add(listItem);

            // create field category dropdown
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionCategory");
            fieldLabel.InnerText = "Question Category";

            listItem.Controls.Add(fieldLabel);

            DropDownList ddlCategories = new DropDownList();
            ddlCategories.ID = "ddlQuestionCategories";
            ddlCategories.ClientIDMode = ClientIDMode.Static;

            List<QuestionCategory> lstCategories = domain.GetCategories();

            // add database items
            foreach (var questionCategory in lstCategories)
            {
                ddlCategories.Items.Add(new ListItem(questionCategory.CategoryDescription, questionCategory.CategoryId.ToString()));
            }

            if (bUpdate)
            {
                foreach (ListItem item in ddlCategories.Items)
                {
                    if (question.Category == Convert.ToInt32(item.Value))
                        item.Selected = true;
                }
            }

            listItem.Controls.Add(ddlCategories);

            uList.Controls.Add(listItem);

            // create field name text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldName");
            fieldLabel.InnerText = "Question Field Name";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldName = new TextBox();
            tbFieldName.ID = "tbFieldName";
            tbFieldName.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldName.Text = question.Name;
            }

            listItem.Controls.Add(tbFieldName);


            uList.Controls.Add(listItem);

            // create field label text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldLabel");
            fieldLabel.InnerText = "Question Field Label";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldLabel = new TextBox();
            tbFieldLabel.ID = "tbFieldLabel";
            tbFieldLabel.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldLabel.Text = question.ContentLabel;
            }

            listItem.Controls.Add(tbFieldLabel);

            RequiredFieldValidator rfvFieldLabel = new RequiredFieldValidator();
            rfvFieldLabel.ControlToValidate = "tbFieldLabel";
            rfvFieldLabel.Display = ValidatorDisplay.Dynamic;
            rfvFieldLabel.ErrorMessage = "Field Label is a required field.";
            rfvFieldLabel.Text = "!";
            rfvFieldLabel.ForeColor = System.Drawing.Color.Red;

            listItem.Controls.Add(rfvFieldLabel);

            uList.Controls.Add(listItem);

            // create field css text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldCSS");
            fieldLabel.InnerText = "Question Field CSS";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldCSS = new TextBox();
            tbFieldCSS.ID = "tbFieldCSS";
            tbFieldCSS.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldCSS.Text = question.FieldCSS;
            }

            listItem.Controls.Add(tbFieldCSS);

            uList.Controls.Add(listItem);

            // create field suffix text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldSuffix");
            fieldLabel.InnerText = "Question Field Suffix";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldSuffix = new TextBox();
            tbFieldSuffix.ID = "tbFieldSuffix";
            tbFieldSuffix.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldSuffix.Text = question.FieldSuffix;
            }

            listItem.Controls.Add(tbFieldSuffix);

            uList.Controls.Add(listItem);

            // create field helptext text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldHelpText");
            fieldLabel.InnerText = "Question Field Help Text";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldHelpText = new TextBox();
            tbFieldHelpText.ID = "tbFieldHelpText";
            tbFieldHelpText.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldHelpText.Text = question.FieldHelpText;
            }

            listItem.Controls.Add(tbFieldHelpText);

            uList.Controls.Add(listItem);

            // create field helpURL text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldHelpURL");
            fieldLabel.InnerText = "Question Field Help URL";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldHelpURL = new TextBox();
            tbFieldHelpURL.ID = "tbFieldHelpURL";
            tbFieldHelpURL.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldHelpURL.Text = question.FieldHelpURL;
            }

            listItem.Controls.Add(tbFieldHelpURL);

            uList.Controls.Add(listItem);

            // create field helpURL text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionActive");
            fieldLabel.InnerText = "Question Active";

            listItem.Controls.Add(fieldLabel);

            CheckBox cbQuestionActive = new CheckBox();
            cbQuestionActive.ID = "cbQuestionActive";
            cbQuestionActive.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                cbQuestionActive.Checked = question.FieldActive;
            }
            else
            {
                cbQuestionActive.Checked = true;
            }

            listItem.Controls.Add(cbQuestionActive);

            uList.Controls.Add(listItem);

            panel.Controls.Add(uList);

            panel.Visible = true;
        }

        /// <summary>
        /// ProcessAdminForm - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="question"></param>
        /// <param name="panelList"></param>
        /// <returns></returns>
        public void ProcessAdminForm(Question question, List<Panel> panelList)
        {
            Panel panelBuild;

            foreach (Panel panel in panelList)
            {
                panelBuild = panel;
                switch (panel.ID)
                {
                    case "pnlQuestionCore":
                        ProcessQuestionPanel(panelBuild, ref question);
                        break;
                    case "pnlOptions":
                        ProcessOptionPanel(panelBuild);
                        break;
                    case "pnlProcessingRules":
                        ProcessProcessingPanel(panelBuild);
                        break;
                }
            }

            //TODO change to full question update and add
            Domain domain = new Domain();

            if (question.Id != 0)
            {
                domain.UpdateQuestionCore(question);
                domain.UpdateQuestionStatusByValue(question.Id, question.FieldActive);
            }
            else
            {
                //get last sort order
                int lastSort = 0;
                List<Question> listQ = domain.RetrieveQuestions(question.Category);
                foreach (Question q in listQ)
                {
                    lastSort = q.SortOrder;
                }

                question.SortOrder = lastSort + 1;

                int nIdentity = domain.InsertQuestionCore(question);
                if (nIdentity != 0)
                    domain.UpdateQuestionStatusByValue(nIdentity, question.FieldActive);
            }


        }

        /// <summary>
        /// ProcessProcessingPanel - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="panelBuild"></param>
        private void ProcessProcessingPanel(Panel panelBuild)
        {
            //TODO build process logic
        }

        /// <summary>
        /// ProcessOptionPanel - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="panelBuild"></param>
        private void ProcessOptionPanel(Panel panelBuild)
        {
            //TODO build option logic
        }

        /// <summary>
        /// ProcessQuestionPanel - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="panelBuild"></param>
        /// <param name="question"></param>
        private void ProcessQuestionPanel(Panel panelBuild, ref Question question)
        {

            DropDownList ddlQuestionTypes = (DropDownList)panelBuild.FindControl("ddlQuestionTypes");
            question.DisplayType = ddlQuestionTypes.SelectedValue;

            DropDownList ddlCategories = (DropDownList)panelBuild.FindControl("ddlQuestionCategories");
            question.Category = Convert.ToInt32(ddlCategories.SelectedValue);

            TextBox tbFieldName = (TextBox)panelBuild.FindControl("tbFieldName");
            question.Name = tbFieldName.Text;

            TextBox tbFieldLabel = (TextBox)panelBuild.FindControl("tbFieldLabel");
            question.ContentLabel = tbFieldLabel.Text;

            TextBox tbFieldCSS = (TextBox)panelBuild.FindControl("tbFieldCSS");
            question.FieldCSS = tbFieldCSS.Text;

            TextBox tbFieldSuffix = (TextBox)panelBuild.FindControl("tbFieldSuffix");
            question.FieldSuffix = tbFieldSuffix.Text;

            TextBox tbFieldHelpText = (TextBox)panelBuild.FindControl("tbFieldHelpText");
            question.FieldHelpText = tbFieldHelpText.Text;

            TextBox tbFieldHelpURL = (TextBox)panelBuild.FindControl("tbFieldHelpURL");
            question.FieldHelpURL = tbFieldHelpURL.Text;

            CheckBox cbQuestionActive = (CheckBox)panelBuild.FindControl("cbQuestionActive");
            question.FieldActive = cbQuestionActive.Checked;

        }

        #endregion
    }
}